﻿class Clock3D extends MovieClip {
	private var bg:Array = new Array();
	private var hour:Array = new Array();
	private var min:Array = new Array();
	private var sec:Array = new Array();
	
	private var vpX:Number = Stage.width/2;
	private var vpY:Number = Stage.height/2;
	
	private var angleX:Number = 0;
	private var angleY:Number = 0;
	
	public function Clock3D() {
		init();
		onEnterFrame = loop;
		Key.addListener({onKeyDown:mx.utils.Delegate.create(this, keyDownHandler)});
	}
	
	private function init():Void {
		for(var i:Number=0; i<12; i++){
			bg.push({p3d:new Point3D(0, 0, 0), mc:getBall(0, String(i))});
			bg[bg.length-1].p3d.setVanishingPoint(vpX, vpY);
			bg[bg.length-1].p3d.setCenter(0, 0, 0);
		}
		
		for(var i:Number=0; i<5; i++){
			hour.push({p3d:new Point3D(0, 0, 0), mc:getBall(5)});
			hour[hour.length-1].p3d.setVanishingPoint(vpX, vpY);
			hour[hour.length-1].p3d.setCenter(0, 0, 0);
		}
		for(var i:Number=0; i<7; i++){
			min.push({p3d:new Point3D(0, 0, 0), mc:getBall(4)});
			min[min.length-1].p3d.setVanishingPoint(vpX, vpY);
			min[min.length-1].p3d.setCenter(0, 0, 0);
		}
		for(var i:Number=0; i<9; i++){
			sec.push({p3d:new Point3D(0, 0, 0), mc:getBall(3)});
			sec[sec.length-1].p3d.setVanishingPoint(vpX, vpY);
			sec[sec.length-1].p3d.setCenter(0, 0, 0);
		}		
	}
	
	private function getBall(size:Number, txt:String):MovieClip{
		var depth:Number = this.getNextHighestDepth();
		var ball_mc:MovieClip = this.createEmptyMovieClip("ball" + depth, depth);

		if(size!=0){			
			ball_mc.lineStyle(0, 0x000000, 100);
			var curveCount:Number = 16;
			var dAngle:Number = (2*Math.PI)/curveCount;
			var dCos:Number = Math.cos(dAngle);
			var dSin:Number = Math.sin(dAngle);
			var dAngle2:Number = dAngle/2;
			var dCos2:Number = Math.cos(dAngle2);
			var dSin2:Number = Math.sin(dAngle2);
			var x1:Number = size/2;
			var y1:Number = 0;
			ball_mc.moveTo(x1, y1);
			ball_mc.beginFill(Math.random() * 0xffffff, 100);
			for (var i:Number = 0; i<curveCount; i++) {
				var x2:Number = dCos*x1-dSin*y1;
				var y2:Number = dCos*y1+dSin*x1;
				var xCon:Number = dCos2*x1-dSin2*y1;
				var yCon:Number = dCos2*y1+dSin2*x1;
				ball_mc.curveTo(xCon, yCon, x2, y2);
				x1 = x2;
				y1 = y2;
			}
			ball_mc.endFill();
		}
		
		if(txt!=null && txt!=""){
			ball_mc.createTextField("_txt", 2, 0, 0, 20, 20);
			ball_mc._txt.autoSize = true;
			ball_mc._txt.text = txt;
			ball_mc._txt._x = -ball_mc._txt._width/2;
			ball_mc._txt._y = -ball_mc._txt._height/2;
		}
		
		return ball_mc;		
	}
	
	private function updateBalls():Void{
		var ary:Array = [bg, hour, min, sec];
		
		for(var j:Number=0; j<ary.length; j++){
			for(var i:Number=0; i<ary[j].length; i++){
				if(ary[j][i].p3d.screenX>=0&&ary[j][i].p3d.screenX<=Stage.width
					&&ary[j][i].p3d.screenY>=0&&ary[j][i].p3d.screenY<=Stage.height){
					ary[j][i].mc._visible = true;
					ary[j][i].mc._x = ary[j][i].p3d.screenX;
					ary[j][i].mc._y = ary[j][i].p3d.screenY;
					ary[j][i].mc._alpha = ary[j][i].p3d.scale * 100;
					ary[j][i].mc._xscale = ary[j][i].mc._yscale = ary[j][i].p3d.scale * 100;
				}else{
					ary[j][i].mc._visible = false;
				}
			}
		}
	}
	
	private function updateBallsByTime():Void{
		var x:Number = 0;
		var y:Number = 0;
		var z:Number = 0;
		
		var a:Number = Math.PI / 180;

		for(var i:Number=0; i<bg.length; i++){
			bg[i].p3d.x = 100;
			bg[i].p3d.y = 0;
			bg[i].p3d.z = 0;
			bg[i].p3d.rotateZ(((i*5) / 60) * 2 * Math.PI - 0.5 * Math.PI);
		}
		
		var dt:Date = new Date();
		var s:Number = dt.getSeconds() + dt.getMilliseconds() / 1000;
		var n:Number = dt.getMinutes() + s / 60;
		var h:Number = dt.getHours() + n / 60;
		
		h = (h / 12) * 2 * Math.PI - 0.5 * Math.PI;
		n = (n / 60) * 2 * Math.PI - 0.5 * Math.PI;
		s = (s / 60) * 2 * Math.PI - 0.5 * Math.PI;

		for(var i:Number=0; i<hour.length; i++){
			hour[i].p3d.x = 10 * i;
			hour[i].p3d.y = 0;
			hour[i].p3d.z = 0;
			hour[i].p3d.rotateZ(h);
		}
		for(var i:Number=0; i<min.length; i++){
			min[i].p3d.x = 10 * i;
			min[i].p3d.y = 0;
			min[i].p3d.z = 0;
			min[i].p3d.rotateZ(n);
		}
		for(var i:Number=0; i<sec.length; i++){
			sec[i].p3d.x = 10 * i;
			sec[i].p3d.y = 0;
			sec[i].p3d.z = 0;
			sec[i].p3d.rotateZ(s);
		}
	}
	
	private function loop():Void{
		
		updateBallsByTime();
		
		var ary:Array = [bg, hour, min, sec];
		
		for(var j:Number=0; j<ary.length; j++){
			for(var i:Number=0; i<ary[j].length; i++){
				ary[j][i].p3d.rotateX(angleX);
				ary[j][i].p3d.rotateY(angleY);
			}
		}

		updateBalls();
	}
	
	private function keyDownHandler():Void{
		switch(Key.getCode()){
			case Key.UP:
				angleX -= 0.1;
				break;
			case Key.DOWN:
				angleX += 0.1;
				break;
			case Key.LEFT:
				angleY -= 0.1;
				break;
			case Key.RIGHT:
				angleY += 0.1;
				break;
		}
	}
}
